

package com.beans;

import com.entidades.Negocios;
import org.apache.commons.mail.*;
import com.entidades.Usuarios;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.servlet.http.HttpSession;
import javax.transaction.NotSupportedException;
import javax.transaction.Transactional;
import javax.transaction.UserTransaction;
import org.primefaces.event.FileUploadEvent;  
import org.primefaces.model.UploadedFile;  

/**
 * <p>A simple managed bean to mediate between the user
 * and the persistence layer.</p>
 * @author rlubke
 */
public class UserManager {
    
    /**
     * <p>The key for the session scoped attribute holding the
     * appropriate <code>Wuser</code> instance.</p>
     */
    public static final String USER_SESSION_KEY = "user";
    
    /**
     * <p>The <code>PersistenceContext</code>.</p>
     */
    @PersistenceContext 
    private EntityManager em;
    
    /**
     * <p>The transaction resource.</p>
     */
    @Resource 
    private UserTransaction utx;
    
    /**
     * <p>User properties.</p>
     */
    private String username;
    private String password;
    private String passwordv;
    private String email;   
    

    
    // -------------------------------------------------------------- Properties
    public String getEmail() {
        return email;
    }
    
    public void setEmail(String email) {
        this.email = email;
    }
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public String getPassword() {
        return password;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    public String getPasswordv() {
        return passwordv;
    }
    
    public void setPasswordv(String passwordv) {
        this.passwordv = passwordv;
    }
    
    // ---------------------------------------------------------- Public Methods
    
    
    /**
     * <p>Validates the user.  If the user doesn't exist or the password
     * is incorrect, the appropriate message is added to the current
     * <code>FacesContext</code>.  If the user successfully authenticates,
     * navigate them to the page referenced by the outcome <code>app-main</code>.
     * </p>
     *
     * @return <code>app-main</code> if the user authenticates, otherwise
     *  returns <code>null</code>
     */
    public String validateUser() {   
        FacesContext context = FacesContext.getCurrentInstance();
        Usuarios user = getUser();
        System.out.println("Entra a validar usuario...");
        //System.out.println("GetUser::: " + user.getIdUsuario().toString());
        if (user != null) {
            if (!user.getUsuPassword().equals(password)) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                           context.getApplication().evaluateExpressionGet(context, "Login incorrecto.", String.class)
                                           ,"Login error.");
                context.addMessage("logingrowl", message);
                return null;
            }
            if(!user.getUsuEmailValidado().equals(0)){
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                           context.getApplication().evaluateExpressionGet(context, "Pendiente verificacion de email.", String.class)
                                           ,"Login error.");
                context.addMessage("logingrowl", message);
                return null;
            }
            
            context.getExternalContext().getSessionMap().put(USER_SESSION_KEY, user);
            
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
                    context.getApplication().evaluateExpressionGet(context, user.getUsuUsuario() + ", Bienvenido!", String.class)
                    ,null);
            context.addMessage("logingrowl", message);
            
            setTipoUsuario(user.getIdUsuario());
            
            //pone la variable de sesion "SPAGINA" para que sea index
            Map sMap;
            sMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
            controlPrincipal bm = (controlPrincipal) sMap.get("cPri");
            bm.pagCentro = "index";
            
            return null;
            //return "app-main";
        } else {           
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "Login incorrecto.", String.class)
                    ,null);
            context.addMessage("logingrowl", message);
            return null;
        }
    }
    
    /**
     * <p>Creates a new <code>Wuser</code>.  If the specified user name exists
     * or an error occurs when persisting the Wuser instance, enqueue a message
     * detailing the problem to the <code>FacesContext</code>.  If the 
     * user is created, move the user back to the login view.</p>
     *
     * @return <code>login</code> if the user is created, otherwise
     *  returns <code>null</code>
     */
    public String createUser() {
        FacesContext context = FacesContext.getCurrentInstance();
        Usuarios wuser = getUser();
        if (wuser == null) {
            if (!password.equals(passwordv)) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                        context.getApplication().evaluateExpressionGet(context, "Las passwords no coinciden", String.class)
                        ,null);
                context.addMessage("creategrowl", message);
                return null;
            }
            wuser = new Usuarios();
            wuser.setUsuUsuario(username);
            wuser.setUsuPassword(password);
            wuser.setUsuEmail(email);
            wuser.setUsuNegocio(0);
            wuser.setUsuTipo(0);
            Integer numeroAleatorio = (int) (Math.random()* 1999999999+1);
            wuser.setUsuEmailValidado(numeroAleatorio);

            
            
            try {
                utx.begin();
                em.persist(wuser);
                utx.commit();
                
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
                    context.getApplication().evaluateExpressionGet(context, "Cuenta creada!", String.class)
                    ,null);
                context.addMessage("creategrowl", message);
                
                
                //pone la variable de sesion "SPAGINA" para que sea index
                Map sMap;
                sMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
                controlPrincipal bm = (controlPrincipal) sMap.get("cPri");
                bm.pagCentro = "index";
                
                //finalmente envia el email de verificacion
                enviarEmailverificacion(email, numeroAleatorio, getUser().getIdUsuario());
                
                //return "app-main";
                return null;
            } catch (Exception e) {               
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                                        "Error creando usuario!",
                                                        "Error inesperado creando usuario. Por favor, contacta con el administrador.");
                context.addMessage(null, message);
                Logger.getAnonymousLogger().log(Level.SEVERE,
                                                "Imposible crear usuario.",
                                                e);
                return null;
            }
        } else {           
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                                    "El usuario '"
                                                      + username 
                                                      + "' ya existe!  ",
                                                    "Por favor, elige un nombre de usuario diferente.");
            context.addMessage(null, message);
            return null;
        }        
    }
    
    
    /**
     * <p>When invoked, it will invalidate the user's session
     * and move them to the login view.</p>
     *
     * @return <code>login</code>
     */
    public String logout() {
        HttpSession session = (HttpSession)
             FacesContext.getCurrentInstance().getExternalContext().getSession(false);
        if (session != null) {
            session.invalidate();
        }
        //return "login";
        return "app-main";
        
    }
    
    // --------------------------------------------------------- Private Methods
    
    
    /**
     * <p>This will attempt to lookup a <code>Wuser</code> object
     * based on the provided user name.</p>
     *
     * @return a <code>Wuser</code> object associated with the current
     *  username, otherwise, if no <code>Wuser</code> can be found,
     *  returns <code>null</code>
     */
    public Usuarios getUser() {
        try {
            Usuarios user = (Usuarios)
            em.createNamedQuery("Usuarios.findByUsuUsuario").
                    setParameter("usuUsuario", username).getSingleResult();
            return user; 
        } catch (NoResultException nre) {
            return null;
        }
    }
    
    public String getNombreUser(Integer iduser) {
        try {
            Usuarios user = (Usuarios)
            em.createNamedQuery("Usuarios.findByIdUsuario").
                    setParameter("idUsuario", iduser).getSingleResult();
            return user.getUsuUsuario(); 
        } catch (NoResultException nre) {
            return null;
        }
    }

    public void setTipoUsuario(Integer idUser) {
        Map sMap;
        sMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
        controlPrincipal bm = (controlPrincipal) sMap.get("cPri");
        try {
            Usuarios use = (Usuarios)
            em.createNamedQuery("Usuarios.findByIdUsuario").
                    setParameter("idUsuario", idUser).getSingleResult();
            bm.esUsuario = true;
            
            if(use.getUsuTipo().equals(1)){
                bm.esNegocio = true;
            }else{
                bm.esNegocio = false;
            }
            if(use.getUsuTipo().equals(2)){
                bm.esAdmin = true;
            }else{
                bm.esAdmin = false;
            }
            
        } catch (NoResultException nre) {
            bm.esUsuario = false;
            bm.esNegocio = false;
            bm.esAdmin = false;
        }
        
    }
   
    public String checkUsuario(String userNombre) {
        Query query = em.createNamedQuery("Usuarios.findByUsuUsuario");
        String paramLike = userNombre;
        query.setParameter("usuUsuario", paramLike);
        List<Usuarios> tmpUsuarios = query.getResultList();
        
        if(tmpUsuarios.size() > 0){
            return "Nombre de usuario ya existente.";
        }
        if(userNombre.length() < 4){
            return "Minimo 4 carecteres.";
        }
        if(userNombre.length() > 24){
            return "Máximo 24 carecteres.";
        }       
        
        
        return "Ok!";
    }
    public void isUsernameValid(FacesContext ctx, UIComponent component, Object  value) throws ValidatorException
	{
                String userNombre = value.toString();
		Query query = em.createNamedQuery("Usuarios.findByUsuUsuario");
                String paramLike = userNombre;
                query.setParameter("usuUsuario", paramLike);
                List<Usuarios> tmpUsuarios = query.getResultList();
                FacesContext context = FacesContext.getCurrentInstance();
                
                if(tmpUsuarios.size() > 0){
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "El usuario ya existe.", String.class)
                        ,null);
                    //context.addMessage(null, message);
			//throw new ValidatorException( context.getMessageList().get(context.getMessageList().size()-1));
                    throw new ValidatorException(message);
                }
                
                if(userNombre.length() < 4){
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "Minimo 4 caracteres.", String.class)
                        ,null);
                    //context.addMessage(null, message);
			//throw new ValidatorException(  context.getMessageList().get(context.getMessageList().size()-1));
                    throw new ValidatorException(message);
                }
                if(userNombre.length() > 24){
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "Maximo 24 caracteres.", String.class)
                        ,null);
                    //context.addMessage(null, message);
			//throw new ValidatorException( context.getMessageList().get(context.getMessageList().size()-1));
                        throw new ValidatorException(message);
                }
                if(userNombre.contains(" ") ){
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "No puede contener espacios.", String.class)
                        ,null);
                    //context.addMessage(null, message);
			//throw new ValidatorException( context.getMessageList().get(context.getMessageList().size()-1));
                        throw new ValidatorException(message);
                } 

		
 
	}
    
        public void isNegNombreValid(FacesContext ctx, UIComponent component, Object  value) throws ValidatorException
	{
                String negNombre = value.toString();
		Query query = em.createNamedQuery("Negocios.findByNegNombre");
                String paramLike = negNombre;
                query.setParameter("negNombre", paramLike);
                List<Negocios> tmpNegocios = query.getResultList();
                FacesContext context = FacesContext.getCurrentInstance();
                
                if(tmpNegocios.size() > 0){
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "El nombre de negocio ya existe.", String.class)
                        ,null);
                    //context.addMessage(null, message);
			//throw new ValidatorException( context.getMessageList().get(context.getMessageList().size()-1));
                    throw new ValidatorException(message);
                }
                
                if(negNombre.length() < 2){
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "Minimo 2 caracteres.", String.class)
                        ,null);
                    //context.addMessage(null, message);
			//throw new ValidatorException(  context.getMessageList().get(context.getMessageList().size()-1));
                    throw new ValidatorException(message);
                }
                if(negNombre.length() > 40){
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "Maximo 40 caracteres.", String.class)
                        ,null);
                    //context.addMessage(null, message);
			//throw new ValidatorException( context.getMessageList().get(context.getMessageList().size()-1));
                        throw new ValidatorException(message);
                }
	}
    
    public void enviarEmailverificacion(String emailTo, Integer numeroAleatorio, Integer userId){
        try{
            Email emailemail = new SimpleEmail();
            emailemail.setHostName("smtp.gmail.com");
            emailemail.setSmtpPort(465);
            //emailemail.setAuthenticator(new DefaultAuthenticator("jvt.desarrollo@gmail.com", "ogaqercowvrothhf"));
            emailemail.setAuthenticator(new DefaultAuthenticator("viscatorrero@gmail.com", "vqwuqniowfnujeat"));
            emailemail.setSSLOnConnect(true);
            emailemail.setFrom("viscatorrero@gmail.com","AgrupadosSA");
            emailemail.setSubject("Confirmacion de email");
            emailemail.setMsg("Link de verificación: " + "http://54.201.42.175:8080/AgrupadosSA/faces/confirmacionemail.xhtml?uNumAle="+numeroAleatorio+"&uId="+userId);
  
            emailemail.addTo(emailTo);
            emailemail.send();
        } catch (Exception nre) {
            System.out.println("Error enviando email de verifiacion: " + nre.getMessage() + " --- " + nre.getLocalizedMessage());
            FacesContext context = FacesContext.getCurrentInstance();
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    context.getApplication().evaluateExpressionGet(context, "Error enviando email de verifiacion.", String.class)
                        ,null);
            context.addMessage(null, message);
        }
    }

    
}
